package com.hyacinth.cloudnote.modules.note.converter;

import com.hyacinth.cloudnote.common.converter.AbstractConverter;
import com.hyacinth.cloudnote.common.exception.ExceptionHolder;
import com.hyacinth.cloudnote.modules.note.dto.NoteDTO;
import com.hyacinth.cloudnote.modules.note.dto.TagDTO;
import com.hyacinth.cloudnote.modules.note.model.Note;
import com.hyacinth.cloudnote.modules.note.model.NoteBook;
import com.hyacinth.cloudnote.modules.note.model.NoteTag;
import com.hyacinth.cloudnote.modules.note.repository.NoteBookRepository;
import com.hyacinth.cloudnote.modules.note.repository.NoteRepository;
import com.hyacinth.cloudnote.modules.note.repository.NoteTagRepository;
import lombok.NonNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

import static com.hyacinth.cloudnote.modules.common.errorcode.NoteErrorCode.E1000000001;

/**
 * Note实体与DTO之间接口数据转换实现
 * @author zhangfb
 */
@Component
public class NoteConverter extends AbstractConverter<Note, NoteDTO> {

    @Autowired
    private TagConverter tagConverter;
    @Autowired
    private NoteTagRepository noteTagRepository;
    @Autowired
    private NoteRepository noteRepository;
    @Autowired
    private NoteBookRepository noteBookRepository;

    @Override
    public Note toModel(@NonNull final NoteDTO dto) {
        if (dto.isNew()) {
            return constructModel(dto);
        } else {
            return updateModel(dto);
        }
    }

    @Override
    public NoteDTO toDTO(@NonNull final Note model) {
        final NoteDTO dto = new NoteDTO();

        dto.setId(model.getId());
        dto.setTitle(model.getTitle());
        dto.setNoteBookId(model.getNoteBook().getId());
        dto.setNoteBookName(model.getNoteBook().getName());
        List<NoteTag> noteTags = noteTagRepository.findByNote(model);
        if (!CollectionUtils.isEmpty(noteTags)) {
            List<TagDTO> tags = noteTags.stream()
                    .map(noteTag -> tagConverter.toDTO(noteTag.getTag())).collect(Collectors.toList());
            dto.setTags(tags);
        }
        dto.setContent(model.getContent());
        this.convertCommonToDTO(model, dto);
        return dto;
    }

    /**
     * 构建新Model
     */
    private Note constructModel(final NoteDTO dto) {
        final Note model = new Note();
        UUID noteBookId = dto.getNoteBookId();
        NoteBook noteBook = noteBookRepository.findById(noteBookId).
                orElseThrow(() -> ExceptionHolder.serviceException(E1000000001, "笔记本-" + noteBookId));
        model.setNoteBook(noteBook);
        this.dtoToModel(dto, model);
        return model;
    }

     /**
      * 更新Model
      */
    private Note updateModel(final NoteDTO dto) {
        final Note model = this.noteRepository.findById(dto.getId())
                        .orElseThrow(() -> ExceptionHolder.serviceException(E1000000001, "笔记-" + dto.getId()));
        this.dtoToModel(dto, model);
        return model;
    }

    private void dtoToModel(final NoteDTO dto, final Note model) {
        model.setTitle(dto.getTitle());
        model.setContent(dto.getContent());
    }
}
